package kbproposal

import (
	"context"
	"strings"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/service/backend/common/utils/pointy"
	"mall/service/blog/model"
	"mall/service/blog/rpc/internal/svc"
	"mall/service/blog/rpc/internal/utils/errorhandler"
	"mall/service/blog/rpc/types/blog"

	"github.com/zeromicro/go-zero/core/logx"
)

type BackendProposalListLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewBackendProposalListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BackendProposalListLogic {
	return &BackendProposalListLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

// group: kbproposal
func (l *BackendProposalListLogic) BackendProposalList(in *blog.BackendProposalListReq) (*blog.BackendProposalListResp, error) {
	var orderBys []string
	if len(in.OrderBy) > 0 {
		for _, orderBy := range in.OrderBy {
			var order string = " ASC"
			if orderBy.Order == "1" {
				order = " DESC"
			}
			if orderBy.Field == "id" {
				orderBys = append(orderBys, model.BlogKnowledgeBaseProposalColumns.ID + order)
			}
		}
	}

	var stati string
	if len(in.FilterBy) > 0 {
		for _, filterBy := range in.FilterBy {
			if filterBy.Field == "status" {
				stati = filterBy.In
			}
		}
	}

	var page uint64
	var pageSize uint64
	var restricted bool
	filterMap := make(map[string]map[string][]any)
	if in.Ids != nil {
		if vals := modelx.UniqueInterfaces(*in.Ids, 64); len(vals) > 0 {
			filterMap[model.BlogKnowledgeBaseProposalColumns.ID] = map[string][]any{
				"in": vals,
			}
			restricted = true
		}
	}
	if !restricted {
		page = in.Page
		pageSize = in.PageSize
	}

	statusIn := modelx.UniqueInterfaces(stati, 32)
	postStatusMap := make(map[string][]any)
	if len(statusIn) > 0 {
		postStatusMap["in"] = statusIn
	}
	if in.Status != nil && *in.Status > 0 {
		postStatusMap["equalTo"] = []any{*in.Status - 1}
	}
	if in.WithDeleted != nil && *in.WithDeleted > 0 {
		//
	} else {
		postStatusMap["notEqualTo"] = []any{globalkey.StatusDeleted}
	}
	filterMap[model.BlogKnowledgeBaseProposalColumns.PostStatus] = postStatusMap

	if in.AuthorId != nil {
		filterMap[model.BlogKnowledgeBaseProposalColumns.PostAuthorID] = map[string][]any{
			"equalTo": []any{*in.AuthorId},
		}
	}
	if in.AuthorNickname != nil {
		filterMap[model.BlogKnowledgeBaseProposalColumns.PostAuthorNickname] = map[string][]any{
			"equalTo": []any{*in.AuthorNickname},
		}
	}
	if in.KBEntryId != nil {
		filterMap[model.BlogKnowledgeBaseProposalColumns.PostParentID] = map[string][]any{
			"equalTo": []any{*in.KBEntryId},
		}
	}

	res, count, err := l.svcCtx.KBProposal.GetList(l.ctx, model.M{
		"page":     page,
		"pageSize": pageSize,
		"orderBy":  strings.Join(orderBys, ","),
	}, 1, filterMap)
	if err != nil {
		return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
	}

	resp := &blog.BackendProposalListResp{
		Total: uint64(count),
	}

	if len(res) > 0 {
		idEntryMap := make(map[uint64]*blog.KBEntryInfo)
		eidMap := make(map[uint64]struct{})
		var eids []any
		for _, v := range res {
			if _, ok := eidMap[v.PostParentID]; !ok {
				eids = append(eids, v.PostParentID)
				eidMap[v.PostParentID] = struct{}{}
			}
		}

		subFilterMap := make(map[string]map[string][]any)
		subFilterMap[model.BlogKnowledgeBasisColumns.ID] = map[string][]any{
			"in": eids,
		}
		entries, _, err := l.svcCtx.KBEntry.GetList(l.ctx, model.M{}, -1, subFilterMap)
		if err != nil {
			return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}

		if len(entries) > 0 {
			for _, v := range entries {
				if _, ok := idEntryMap[v.ID]; !ok {
					idEntryMap[v.ID] = &blog.KBEntryInfo{
						Id:      &v.ID,
						Title:   &v.PostTitle,
						Slug:    &v.PostName,
						Excerpt: &v.PostExcerpt,
						Status:  pointy.GetPointer(uint32(v.PostStatus)),
					}
				}
			}
		}

		for _, v := range res {
			var KBEntry *blog.KBEntryInfo
			if entry, ok := idEntryMap[v.PostParentID]; ok {
				KBEntry = entry
			}
			resp.List = append(resp.List, &blog.ProposalInfo{
				Id:             &v.ID,
				AuthorId:       &v.PostAuthorID,
				AuthorNickname: &v.PostAuthorNickname,
				AuthorAvatar:   &v.PostAuthorAvatar,
				AuthorLevel:    pointy.GetPointer(uint32(v.PostAuthorLevel)),
				KBEntryId:      &v.PostParentID,
				Content:        &v.PostContent,
				Perfumers:      &v.Perfumers,
				MainAccords:    &v.FragranceFamilies,
				TopNotes:       &v.TopNotes,
				MiddleNotes:    &v.HeartNotes,
				BaseNotes:      &v.BaseNotes,
				Year:           &v.Year,
				Status:         pointy.GetPointer(uint32(v.PostStatus)),
				CreatedAt:      pointy.GetPointer(modelx.FormatTime(v.PostDate, "")),
				UpdatedAt:      pointy.GetPointer(modelx.FormatTime(v.PostModifiedDate, "")),
				KBEntry:        KBEntry,
			})
		}
	}

	return resp, nil
}
